package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

var (
	DataBase = flag.String("db", "test", "set databases name")
	DBaddr   = flag.String("addr", "127.0.0.1:3306", "databases addr")
	user     = flag.String("u", "root", "databases user name")
	passwd   = flag.String("p", "root", "databases password")
	webaddr  = flag.String("web", ":8002", "web server address")
)

type Where struct {
	Express string        `json:"expr"`
	Value   []interface{} `json:"value"`
}
type Update struct {
	Wher *Where                 `json:"where"`
	Tab  map[string]interface{} `json:"table"`
}
type Delete struct {
	Wher *Where    `json:"where"`
	Tab  *UserInfo `json:"table"`
}

// 1.定义数据库模型
type UserInfo struct {
	Id      int    `json:"id"` //字段要大写首字母
	Name    string `json:"name" gorm:"default:'小王子'"`
	Kind    string `json:"kind"`
	Describ string `json:"describ"`
}

func initdb(value ...interface{}) *gorm.DB {
	// DSN:Data Source Name
	dsn := *user + ":" + *passwd + "@tcp(" + *DBaddr + ")/" + *DataBase + "?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open("mysql", dsn)
	if err != nil {
		panic(err)
	}
	// 2.把模型与数据库中表关联起来(创建表,自动迁移,根据结构体创建表)
	db.AutoMigrate(value...)
	fmt.Println("初始化数据库成功......")
	return db
}

func main() {
	flag.Func()
	flag.Parse()
	//server(&UserInfo{},func (value ...interface{}) *gorm.DB  {
		// 自定义初始化orm
	//})
	fmt.Println(server(initdb, &UserInfo{}))
}

func server(orm func(value ...interface{}) *gorm.DB, curd ...interface{}) error {
	db := orm(curd)
	defer db.Close()
	router := gin.Default()
	/* 查询
	Where表达式:
	1.("name = ?", "jinzhu")
	2.("name <> ?", "jinzhu")
	3.("name IN (?)", []string{"jinzhu", "jinzhu 2"})
	4.("name LIKE ?", "%jin%")
	5.("name = ? AND age >= ?", "jinzhu", "22")
	6.("updated_at > ?", lastWeek)
	7.("created_at BETWEEN ? AND ?", lastWeek, today)
	*/
	router.POST("/r", func(ctx *gin.Context) {
		where := &Where{Value: make([]interface{}, 1)}
		out := []UserInfo{}
		//获取json
		req, err := ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			fmt.Println(err)
			ctx.JSON(http.StatusBadGateway, where)
			return
		}
		err = json.Unmarshal(req, where)
		if err != nil {
			ctx.JSON(http.StatusBadRequest, where)
			return
		}
		err = db.Find(&out, where.Express, where.Value).Error
		if err != nil {
			ctx.JSON(http.StatusBadGateway, where)
		}
		//返回结果
		//fmt.Fprintln(ctx.Writer, "查询表达式:")
		//ctx.JSON(200, where)
		//fmt.Fprintln(ctx.Writer, "\n查询结果:")
		ctx.JSON(200, out)
	})
	router.POST("/w", func(ctx *gin.Context) {
		in := &UserInfo{}
		//获取jsons
		//db1 := &UserInfo{Name: "hhh", Kind: "OOO", Describ: "kkk"}
		req, err := ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			fmt.Println(err)
			ctx.JSON(http.StatusBadGateway, in)
			return
		}
		err = json.Unmarshal(req, in)
		if err != nil {
			ctx.JSON(http.StatusBadRequest, in)
			return
		}
		//插入数据库
		err = db.Debug().Create(in).Error
		if err != nil {
			ctx.JSON(http.StatusBadGateway, in)
			return
		}
		//返回结果
		ctx.JSON(200, in)
	})
	router.POST("/d", func(ctx *gin.Context) {
		in := &Delete{Wher: &Where{Value: make([]interface{}, 1)}}
		//获取jsons
		//db1 := &UserInfo{Name: "hhh", Kind: "OOO", Describ: "kkk"}
		req, err := ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			fmt.Println(err)
			ctx.JSON(http.StatusBadGateway, in)
			return
		}
		err = json.Unmarshal(req, in.Wher)
		if err != nil {
			ctx.JSON(http.StatusBadRequest, in)
			return
		}
		// 删除
		err = db.Debug().Delete(in.Tab, in.Wher.Express, in.Wher.Value).Error
		if err != nil {
			ctx.JSON(http.StatusBadGateway, in)
			return
		}
		//返回结
		ctx.JSON(200, in)
	})
	router.POST("/u", func(ctx *gin.Context) {
		in := &Update{Wher: &Where{Value: make([]interface{}, 1)}, Tab: make(map[string]interface{})}
		//获取json
		//db1 := &UserInfo{Name: "hhh", Kind: "OOO", Describ: "kkk"}
		req, err := ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			fmt.Println(err)
			ctx.JSON(http.StatusBadGateway, in)
			return
		}
		err = json.Unmarshal(req, in)
		if err != nil {
			ctx.JSON(http.StatusBadRequest, in)
			return
		}
		// 改
		err = db.Debug().Table("user_infos").Where(in.Wher.Express, in.Wher.Value...).Update(in.Tab).Error
		if err != nil {
			ctx.JSON(http.StatusBadGateway, in)
			return
		}
		//返回结果
		ctx.JSON(200, in)
	})
	return router.Run(*webaddr)
}
